// axios 封装
import axios from 'axios'
import type { InternalAxiosRequestConfig } from 'axios'
import Cookies from 'js-cookie'
import { QueryObject, firstItem, mergeArrays, poll, removeEmptyValue } from './utils'
import { CODES } from './code'
import { cloneDeep, isString } from '@/utils'

const baseConfig = {
  timeout: 1000 * 60,
  headers: {
    'Content-Type': 'application/json',
  },
}
export interface AppendOption {
  type: 'account' | 'tunnel'
  listField?: string // 主列表
  mainKey?: string // 主列表的唯一标识字段名
  extraKey?: string // 主列表与附加信息列表的唯一标识
  targetKey?: string // 附加信息放入主列表的字段名
}
export default class Http {
  private instance = axios.create(baseConfig)
  public constructor(module: string) {
    this.instance.defaults.baseURL = `/${module}/api`

    /** === 请求拦截 === */
    this.instance.interceptors.request.use((config: InternalAxiosRequestConfig) => {
      const data = config.data
      const isGet = config.method === 'get'
      if (!isGet) {
        const sessionid = Cookies.get('sessionid')
        if (sessionid) {
          if (config.url === '/hybridwan/v1/monitor/flowAnalysis') {
            config.data.sessionUuid = sessionid
          }
          else {
            const dataFirstValue = firstItem(data) as any
            dataFirstValue.session = { uuid: sessionid }
          }
        }
      }
      return config
    }, (error) => {
      console.error(error)
      return Promise.resolve({})
    })

    /** === 响应拦截 === */
    this.instance.interceptors.response.use((response) => {
      const { data } = response
      if (isString(data)) {
        ElNotification.error({
          title: '请求错误',
          message: data,
        })
        return Promise.resolve({ success: false })
      }
      else {
        const { state } = data
        if (state === 'Processing') {
          return poll(this, response)
        }
        else if (state === 'Done') {
          const result = firstItem(JSON.parse(data.result)) as any
          /** 错误处理 */
          const { success, error } = result
          if (!success && error) {
            /** 若存在对应状态码 */
            if (Object.keys(CODES).includes(error.code)) {
              // ElNotification.error({
              //   title: CODES[error.code],
              //   message: error.details || error.description,
              // })
              // 登录超时
              // if (error.code === 'ID.1001')
              //   location.href = `${import.meta.env.VITE_BASE_PATH}login`
            }
            else {
              ElNotification.error({
                title: '请求错误',
                message: error.details,
              })
            }
          }
          return result
        }
      }
      return response
    }, (error) => {
      console.error(error)
      return Promise.resolve({})
    })
  }

  public get(url: string, params: any) {
    return this.instance.get(url, { params })
  }

  public post(api: string, data: any = {}) {
    const cfg = {
      [api]: removeEmptyValue(data),
    }
    return this.instance.post('', cfg)
  }

  public query(api: string, data: any = {}) {
    let newData = cloneDeep(data)
    if (!(data instanceof QueryObject))
      newData = Object.assign({}, new QueryObject(), data)
    return this.post(api, newData)
  }

  public request(api, data = {}, appendCfg?: AppendOption) {
    // 如果是 APIQuery 消息，则使用 query 方法
    const isQuery = api.includes('APIQuery')
    const result = isQuery ? this.query(api, data) : this.post(api, data)
    if (appendCfg)
      return this.requestAppend(result, appendCfg)
    else
      return result
  }

  /** 额外追加信息的请求 */
  public requestAppend(result, appendCfg?: AppendOption) {
    const { type } = appendCfg
    // 追加Account信息 ，追加Tunnel信息
    if (type === 'account')
      return this.appendAccount(result, appendCfg)
    else if (type === 'tunnel')
      return this.appendTunnel(result, appendCfg)
  }

  public appendAccount(result, appendCfg) {
    const { listField = 'inventories', ...rest } = appendCfg
    const { mainKey = 'accountUuid' } = rest
    const getList = (result) => {
      return result[listField] || []
    }
    return result.then((res) => {
      const list = getList(res)// 取出需要追加的列表
      const uuids = [...new Set(list.map(item => item[mainKey]))]
      return queryAccountByUuids(uuids).then((accountRes: any) => {
        const { inventories = [] } = accountRes
        if (!inventories.length)
          return res
        res[listField] = mergeArrays(list, inventories, rest) // 替换原来的列表
        return res
      })
    })
  }

  public appendTunnel(result, appendCfg) {
    const { listField = 'inventories', ...rest } = appendCfg
    const { mainKey = 'tunnelUuid' } = rest
    const getList = (result) => { return result[listField] }
    return result.then((res) => {
      const list = getList(res)// 取出需要追加的列表
      const uuids = [...new Set(list.map(item => item[mainKey]))]
      return queryTunnelByUuids(uuids).then((tunnelList) => {
        res[listField] = mergeArrays(list, tunnelList, rest) // 替换原来的列表
        return res
      })
    })
  }
}

/** 根据 uuids 查账户信息 */
function queryAccountByUuids(uuids) {
  const apimsg = 'com.syscxp.account.header.account.APIQueryAccountMsg'
  const qobj = new QueryObject(0, uuids.length)
  qobj.fields = ['uuid', 'name', 'company']
  qobj.conditions.push({ name: 'uuid', op: 'in', value: uuids.join(',') })
  return new Http('account').query(apimsg, qobj)
}
function queryTunnelByUuids(uuids) {
  const apimsg = 'com.syscxp.account.header.account.APIQueryAccountMsg'
  const qobj = new QueryObject(0, uuids.length)
  qobj.fields = []
  qobj.conditions.push({ name: 'uuid', op: 'in', value: uuids.join(',') })
  return new Http('tunnel').query(apimsg, qobj)
}
